/****************************************************
    Utility.java: Contains supporting functions to
    help doing dirty jobs for other classes

    Author: Minh B. Do - Arizona State University
 ****************************************************/
package edu.asu.sapa.utils;

import java.lang.reflect.Array;

public class Utility {

	public static final void insert(boolean[] a, int index, boolean v) {
		for (int i = a.length - 1; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(byte[] a, int index, byte v) {
		for (int i = a.length - 1; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(char[] a, int index, char v) {
		for (int i = a.length - 1; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(double[] a, int index, double v) {
		for (int i = a.length - 1; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(float[] a, int index, float v) {
		for (int i = a.length - 1; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(int[] a, int index, int v) {
		for (int i = a.length - 1; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(long[] a, int index, long v) {
		for (int i = a.length - 1; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(Object[] a, int index, Object v) {
		for (int i = a.length - 1; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(short[] a, int index, short v) {
		for (int i = a.length - 1; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(boolean[] a, int index, boolean v, int num) {
		for (int i = num; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(byte[] a, int index, byte v, int num) {
		for (int i = num; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(char[] a, int index, char v, int num) {
		for (int i = num; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(double[] a, int index, double v, int num) {
		for (int i = num; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(float[] a, int index, float v, int num) {
		for (int i = num; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(int[] a, int index, int v, int num) {
		for (int i = num; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(long[] a, int index, long v, int num) {
		for (int i = num; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(Object[] a, int index, Object v, int num) {
		for (int i = num; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}

	public static final void insert(short[] a, int index, short v, int num) {
		for (int i = num; i > index; --i) {
			a[i] = a[i - 1];
		}
		a[index] = v;
	}
	
	public static final void remove(boolean[] a, int index) {
		for (; index < a.length - 1; index++) {
			a[index] = a[index + 1];
		}
	}

	public static final void remove(boolean[] a, int index, int length) {
		for (; index < a.length - length; index++) {
			a[index] = a[index + length];
		}
	}

	public static final void remove(byte[] a, int index) {
		for (; index < a.length - 1; index++) {
			a[index] = a[index + 1];
		}
	}

	public static final void remove(byte[] a, int index, int length) {
		for (; index < a.length - length; index++) {
			a[index] = a[index + length];
		}
	}

	public static final void remove(char[] a, int index) {
		for (; index < a.length - 1; index++) {
			a[index] = a[index + 1];
		}
	}

	public static final void remove(char[] a, int index, int length) {
		for (; index < a.length - length; index++) {
			a[index] = a[index + length];
		}
	}

	public static final void remove(double[] a, int index) {
		for (; index < a.length - 1; index++) {
			a[index] = a[index + 1];
		}
	}

	public static final void remove(double[] a, int index, int length) {
		for (; index < a.length - length; index++) {
			a[index] = a[index + length];
		}
	}

	public static final void remove(float[] a, int index) {
		for (; index < a.length - 1; index++) {
			a[index] = a[index + 1];
		}
	}

	public static final void remove(float[] a, int index, int length) {
		for (; index < a.length - length; index++) {
			a[index] = a[index + length];
		}
	}
	
	public static final void remove(float[] a, int index, int length, int num) {
		for (; index < num - length; index++) {
			a[index] = a[index + length];
		}
	}

	public static final void remove(int[] a, int index) {
		for (; index < a.length - 1; index++) {
			a[index] = a[index + 1];
		}
	}

	public static final void remove(int[] a, int index, int length) {
		for (; index < a.length - length; index++) {
			a[index] = a[index + length];
		}
	}
	
	public static final void remove(int[] a, int index, int length, int num) {
		for (; index < num - length; index++) {
			a[index] = a[index + length];
		}
	}

	public static final void remove(long[] a, int index) {
		for (; index < a.length - 1; index++) {
			a[index] = a[index + 1];
		}
	}

	public static final void remove(long[] a, int index, int length) {
		for (; index < a.length - length; index++) {
			a[index] = a[index + length];
		}
	}

	public static final void remove(Object[] a, int index) {
		for (; index < a.length - 1; index++) {
			a[index] = a[index + 1];
		}
	}

	public static final void remove(Object[] a, int index, int length) {
		for (; index < a.length - length; index++) {
			a[index] = a[index + length];
		}
	}

	public static final void remove(short[] a, int index) {
		for (; index < a.length - 1; index++) {
			a[index] = a[index + 1];
		}
	}

	public static final void remove(short[] a, int index, int length) {
		for (; index < a.length - length; index++) {
			a[index] = a[index + length];
		}
	}
	
	public static final void copyDown(long[] a, int index, int length, int newSize) {
		index+=length;
		for (int i=newSize-1; i >= index; --i) {
			a[i] = a[i-length];
		}
	}
	public static final void copyDown(int[] a, int index, int length, int newSize) {
		index+=length;
		for (int i=newSize-1; i >= index; --i) {
			a[i] = a[i-length];
		}
	}
	
	public static final void copyDown(byte[] a, int index, int length, int newSize) {
		index+=length;
		for (int i=newSize-1; i >= index; --i) {
			a[i] = a[i-length];
		}
	}
	public static final void copyDown(short[] a, int index, int length, int newSize) {
		index+=length;
		for (int i=newSize-1; i >= index; --i) {
			a[i] = a[i-length];
		}
	}
	public static final void copyDown(char[] a, int index, int length, int newSize) {
		index+=length;
		for (int i=newSize-1; i >= index; --i) {
			a[i] = a[i-length];
		}
	}
	public static final void copyDown(boolean[] a, int index, int length, int newSize) {
		index+=length;
		for (int i=newSize-1; i >= index; --i) {
			a[i] = a[i-length];
		}
	}
	public static final void copyDown(float[] a, int index, int length, int newSize) {
		index+=length;
		for (int i=newSize-1; i >= index; --i) {
			a[i] = a[i-length];
		}
	}
	public static final void copyDown(double[] a, int index, int length, int newSize) {
		index+=length;
		for (int i=newSize-1; i >= index; --i) {
			a[i] = a[i-length];
		}
	}
	public static final void copyDown(Object[] a, int index, int length, int newSize) {
		index+=length;
		for (int i=newSize-1; i >= index; --i) {
			a[i] = a[i-length];
		}
	}
	
	public static final boolean[] grow(boolean[] a) {
		boolean[] t = new boolean[a.length + (a.length >> 1) + 1];
		System.arraycopy(a, 0, t, 0, a.length);

		return t;
	}

	public static final float[] grow(float[] a) {
		float[] t = new float[a.length + (a.length >> 1) + 1];
		System.arraycopy(a, 0, t, 0, a.length);

		return t;
	}
	
	public static final float[] grow(float[] a, int newLength) {
		float[] t = new float[newLength];
		System.arraycopy(a,0,t,0,a.length);
		return t;
	}

	public static final byte[] grow(byte[] a) {
		byte[] t = new byte[a.length + (a.length >> 1) + 1];
		System.arraycopy(a, 0, t, 0, a.length);

		return t;
	}
	
	public static final byte[] grow(byte[] a, int newLength) {
		byte[] t = new byte[newLength];
		System.arraycopy(a,0,t,0,a.length);
		return t;
	}


	public static final int[] grow(int[] a) {
		int[] t = new int[a.length + (a.length >> 1) + 1];
		System.arraycopy(a, 0, t, 0, a.length);

		return t;
	}

	// TODO: comapre Array.newInstance + System.arraycopy vs Arrays.copyOf
	
	public static final <T> T[] grow(T[] a) {
		T[] t = (T[])Array.newInstance((Class<T>) a.getClass().getComponentType(), a.length
				+ (a.length >> 1) + 1);
		System.arraycopy(a, 0, t, 0, a.length);

		//return Arrays.copyOf(a,a.length + (a.length>>1)+1);
		return t;
	}
	
	/**
	 * Must increase in size.  Does not pad with nulls.
	 *  
	 * @param <T>
	 * @param a
	 * @param newLength
	 * @return
	 */
	public static final <T> T[] grow(T[] a, int newLength) {
		T[] t = (T[])Array.newInstance((Class<T>) a.getClass().getComponentType(), newLength);
		System.arraycopy(a, 0, t, 0, a.length);
		
		//return Arrays.copyOf(a,newLength);
		return t;
	}
	
	/**
	 * Must decrease in size.
	 * 
	 * @param <T>
	 * @param a
	 * @param newLength
	 * @return
	 */
	public static final <T> T[] trim(T[] a, int newLength) {
		T[] t = (T[])Array.newInstance((Class<T>) a.getClass().getComponentType(), newLength);
		System.arraycopy(a, 0, t, 0, newLength);
		return t;
	}

    public static final boolean equals(long[] a, long[] a2, int length) {
        for (int i=0; i<length; i++)
            if (a[i] != a2[i])
                return false;

        return true;
    }

    public static final boolean equals(int[] a, int[] a2, int length) {
        for (int i=0; i<length; i++)
            if (a[i] != a2[i])
                return false;

        return true;
    }

    public static final boolean equals(short[] a, short a2[], int length) {
        for (int i=0; i<length; i++)
            if (a[i] != a2[i])
                return false;

        return true;
    }

    public static final boolean equals(char[] a, char[] a2, int length) {
        for (int i=0; i<length; i++)
            if (a[i] != a2[i])
                return false;

        return true;
    }

    public static final boolean equals(byte[] a, byte[] a2, int length) {
        for (int i=0; i<length; i++)
            if (a[i] != a2[i])
                return false;

        return true;
    }

    public static final boolean equals(boolean[] a, boolean[] a2, int length) {
        for (int i=0; i<length; i++)
            if (a[i] != a2[i])
                return false;

        return true;
    }

    public static final boolean equals(double[] a, double[] a2, int length) {
        for (int i=0; i<length; i++)
        	if (Double.doubleToRawLongBits(a[i])!=Double.doubleToRawLongBits(a2[i]))
                return false;

        return true;
    }

    public static final boolean equals(float[] a, float[] a2, int length) {
        for (int i=0; i<length; i++)
        	if (Float.floatToRawIntBits(a[i])!=Float.floatToRawIntBits(a2[i]))
                return false;

        return true;
    }

    public static final boolean equals(Object[] a, Object[] a2, int length) {
        for (int i=0; i<length; i++) {
        	if (a[i] != a2[i])
        		return false;
        }

        return true;
    }
	
	
	public static final int indexOf(boolean[] a, boolean e) {
		for (int i = 0; i < a.length; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	public static final int indexOf(byte[] a, byte e) {
		for (int i = 0; i < a.length; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	// Searching

	public static final int indexOf(char[] a, char e) {
		for (int i = 0; i < a.length; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	public static final int indexOf(double[] a, double e) {
		for (int i = 0; i < a.length; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	public static final int indexOf(float[] a, float e) {
		for (int i = 0; i < a.length; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	public static final int indexOf(int[] a, int e) {
		for (int i = 0; i < a.length; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	public static final int indexOf(long[] a, long e) {
		for (int i = 0; i < a.length; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	public static final int indexOf(Object[] a, Object e) {
		if (e == null) {
			for (int i = 0; i < a.length; i++) {
				if (a[i] == null) {
					return i;
				}
			}
		} else {
			for (int i = 0; i < a.length; i++) {
				if (a[i] != null && a[i].equals(e)) {
					return i;
				}
			}
		}
		return -1;
	}

	public static final int indexOf(short[] a, short e) {
		for (int i = 0; i < a.length; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	public static final int indexOf(boolean[] a, boolean e, int size) {
		for (int i = 0; i < size; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	public static final int indexOf(byte[] a, byte e, int size) {
		for (int i = 0; i < size; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	// Searching

	public static final int indexOf(char[] a, char e, int size) {
		for (int i = 0; i < size; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	public static final int indexOf(double[] a, double e, int size) {
		for (int i = 0; i < size; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	public static final int indexOf(float[] a, float e, int size) {
		for (int i = 0; i < size; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	public static final int indexOf(int[] a, int e, int size) {
		for (int i = 0; i < size; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	public static final int indexOf(long[] a, long e, int size) {
		for (int i = 0; i < size; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	public static final int indexOf(Object[] a, Object e, int size) {
		if (e == null) {
			for (int i = 0; i < size; i++) {
				if (a[i] == null) {
					return i;
				}
			}
		} else {
			for (int i = 0; i < size; i++) {
				if (a[i] != null && a[i].equals(e)) {
					return i;
				}
			}
		}
		return -1;
	}

	public static final int indexOf(short[] a, short e, int size) {
		for (int i = 0; i < size; i++) {
			if (a[i] == e) {
				return i;
			}
		}
		return -1;
	}

	public static final void fill(boolean[] a, boolean v) {
		int sz = a.length;
		for (int i=0; i<sz; ++i)
			a[i] = v;
	}
	public static final void fill(int[] a, int v) {
		int sz = a.length;
		for (int i=0; i<sz; ++i)
			a[i] = v;
	}


}
